
#ifndef	TIMER_INC_
#define TIMER_INC_

#ifdef _WIN32
  #include <time.h>
  #include <winnt.h>
#else
    #include <sys/time.h>
    #include <sys/times.h>
    #include <sys/types.h>

	#include "RtTimeValue.h"

  typedef long long int _int64;
#endif

const _int64 us_benchmark = 1000000;
const _int64 us_hour = us_benchmark * 60 * 60;
const _int64 us_minute = us_benchmark * 60;
const _int64 us_second = us_benchmark;
const _int64 ms_benchmark = 1000;
const _int64 ms_hour = ms_benchmark * 60 * 60;
const _int64 ms_minute = ms_benchmark * 60;
const _int64 ms_second = ms_benchmark;

struct timer_policy
{
	unsigned m_Hour;
	unsigned m_Minute;
	unsigned m_Second;
	union Benchmark{
		unsigned m_microsecond;
		unsigned short m_millsecond;
	};
	Benchmark m_bench;

	static void ConvertFromUs( timer_policy & tm, _int64 ustime)
	{
		tm.m_Hour = (unsigned)(ustime / us_hour);
		tm.m_Minute = (unsigned)((ustime % us_hour) / us_minute);
		tm.m_Second = (unsigned)(((ustime % us_hour) % us_minute) / us_second);
		tm.m_bench.m_microsecond = (unsigned)(((ustime % us_hour) % us_minute) % us_second);
	}
	static void ConvertFromMs( timer_policy & tm, _int64 mstime)
	{
		tm.m_Hour = (unsigned)(mstime / ms_hour);
		tm.m_Minute = (unsigned)((mstime % ms_hour) / ms_minute);
		tm.m_Second = (unsigned)(((mstime % ms_hour) % ms_minute) / ms_second);
		tm.m_bench.m_millsecond = (unsigned short)(((mstime % ms_hour) % ms_minute) % ms_second);
	}
};
///rigour to millisecond
struct timer
{
	///Constructor
	timer(_int64 initTime = -1)
	{
#ifdef _WIN32
		QueryPerformanceFrequency(&m_tvf);
#endif
		reset(initTime);
	}
	///reset the time tag
	void reset(_int64 initTime = -1)
	{
		if(-1 == initTime)
			tag_ = now_i();
		else
			tag_ = initTime;
	}

	///get the elapsed times from reset(microsecond)
	_int64 elapsed()
	{
		_int64 nowt = now_i();
		if(nowt < tag_)
		{
			reset();
		}
		return now_i() -  tag_;
	}

	_int64 elapsed_mills()
	{
		return elapsed() / 1000;
	}

	unsigned elapsed_sec()
	{
		return static_cast<unsigned>(elapsed() / 1000000);
	}

	///get the elapsed microseconds
	const static _int64 now() 
	{
#ifdef _WIN32
		LARGE_INTEGER tv, tvf;
		QueryPerformanceFrequency(&tvf);
		if(!QueryPerformanceCounter(&tv))
			return (clock() * 1000000)/ CLOCKS_PER_SEC;
		else
		{
			return static_cast<_int64>(((double)tv.QuadPart / (double)tvf.QuadPart) * 1000000);
		}
#else
		CRtTimeValue tv = CRtTimeValue::GetTimeOfDay();
		return tv.GetSec() * 1000000 + tv.GetUsec();
#endif
	}

	const static _int64 _now_mills()
	{
		return now() / 1000;
	}

	bool overtime(_int64 microTimes)
	{
		return elapsed() >= microTimes;
	}

	bool overtime_mills(_int64 millsTimes)
	{
		return elapsed_mills()  >= millsTimes;
	}

	bool overtime_sec(unsigned secTimes)
	{
		return elapsed_sec() >= secTimes;
	}

	_int64 latest_tag()
	{
		return tag_;
	}
private:
	_int64 now_i()
	{
#ifdef _WIN32
		LARGE_INTEGER tv;
		if(!QueryPerformanceCounter(&tv))
			return (clock() * 1000000)/ CLOCKS_PER_SEC;
		else
		{
			return static_cast<_int64>(((double)tv.QuadPart / (double)m_tvf.QuadPart) * 1000000);
		}
#else
		return now();
#endif
	}
#ifdef _WIN32
	LARGE_INTEGER m_tvf;
#endif
	///the time tag
	_int64	tag_;
};

class ticker{
public:
	ticker(int initTime = -1)
	{
#ifndef _WIN32
		tickps_ = 1000 /  sysconf(_SC_CLK_TCK);
#endif
		reset(initTime);
	}
	///reset the time tag
	void reset(int initTime = -1)
	{
		if(-1 == initTime)
			tag_ = now_i();
		else
			tag_ = initTime;
	}

	///get the elapsed times from reset(millssecond)
	int elapsed()
	{
		int nowt = now_i();
		if(nowt < tag_)
		{
			reset();
		}
		return now_i() -  tag_;
	}

	int elapsed_sec()
	{
		return elapsed() / 1000;
	}

	///get the elapsed millsseconds
	const static int now() 
	{
#ifdef _WIN32
		return ::GetTickCount();
#else
		struct tms tm;
		return (times(&tm) * (1000 /  sysconf(_SC_CLK_TCK)));
#endif
	}

	const static int _now_sec()
	{
		return now() / 1000;
	}

	bool overtime(int microTimes)
	{
		return elapsed() >= microTimes;
	}

	bool overtime_sec(int secTimes)
	{
		return elapsed_sec() >= secTimes;
	}

	_int64 latest_tag()
	{
		return tag_;
	}
private:
	int now_i()
	{
#ifdef _WIN32
		return ::GetTickCount();
#else
		struct tms tm;
		return times(&tm) * tickps_;
#endif
	}
#ifndef _WIN32
	unsigned tickps_;
#endif
	int tag_;
};

#endif





















